﻿using HMaker.Controls;
using HMaker.Events;
using HMaker.Utils;
using HModel;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace HMaker.Dialogs
{
    public partial class ImgEditor : Form
    {
        /// <summary>
        /// 存储当前正在编辑的图片实体
        /// </summary>
        private ImgEntity _ImgEntity;

        /// <summary>
        /// 存储当前正在编辑的图片的备份,以便直接
        /// </summary>
        private Bitmap _BackUp;

        /// <summary>
        /// 数据源
        /// </summary>
        private readonly BindingSource _Binding = new BindingSource();

        /// <summary>
        /// 用于检查偏移量是否输入合法的正则表达式
        /// </summary>
        private static readonly Regex _OffsetRegex = new Regex(@"-?\d,-?\d");

        /// <summary>
        /// 读取或设置当前要进行编辑的图片实体
        /// </summary>
        public ImgEntity ImgEntity
        {
            get => _ImgEntity;
            set
            {
                _ImgEntity = value?.Clone() as ImgEntity;
                if (_ImgEntity != null)
                {
                    if (string.IsNullOrEmpty(value.BaseOffsetStr))
                    {
                        _ImgEntity.BaseOffsetStr = "0,0";
                    }
                    _Binding.DataSource = _ImgEntity;
                    _Binding.ResetBindings(true);

                    _BackUp = BitmapUtils.FromBytes(_ImgEntity.Bin);
                    ResetImage();
                }
                else
                {
                    MessageBox.Show("必须传入一个图片才能进行编辑");
                }
            }
        }

        public ImgEditor()
        {
            InitializeComponent();
            PE_Main.OnScalarChangedEventHandler += PE_Main_OnScalarChangedEventHandler;

            TB_ImgName.DataBindings.Add(new Binding("Text", _Binding, "Name"));
            TB_BaseOffset.DataBindings.Add(new Binding("Text", _Binding, "BaseOffsetStr"));
        }

        private void PE_Main_OnScalarChangedEventHandler(object sender, ScalarChangedEventArgs e)
        {
            NUD_Scalar.Value = e.Scalar;
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (Keys.Control == ModifierKeys)
            {
                if (e.Delta > 0)
                {
                    NUD_Scalar.Value = Math.Min(16, NUD_Scalar.Value + 1);
                }
                else if (e.Delta < 0)
                {
                    NUD_Scalar.Value = Math.Max(1, NUD_Scalar.Value - 1);
                }
            }
        }

        private void ResetImage()
        {
            PE_Main.Image = _BackUp.Clone(new Rectangle(Point.Empty, _BackUp.Size), PixelFormat.Format24bppRgb);
        }

        private void Bn_Trim_Click(object sender, EventArgs e)
        {
            PE_Main.AutoClipIt();
        }

        private void TB_Fill_TextChanged(object sender, EventArgs e)
        {
            if (int.TryParse(TB_Fill.Text, NumberStyles.HexNumber, NumberFormatInfo.CurrentInfo, out int result))
            {
                TB_Fill.BackColor = Color.FromArgb(result & 0xFFFFFF | unchecked((int)0xFF000000u));
            }
            else
            {
                TB_Fill.BackColor = Color.Black;
            }
        }

        private void TB_Fill_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            CD_Color.Color = TB_Fill.BackColor;
            if (CD_Color.ShowDialog() == DialogResult.Yes)
            {
                TB_Fill.Text = CD_Color.Color.ToArgb().ToString("X2");
            }
        }

        private void TB_Fill_BackColorChanged(object sender, EventArgs e)
        {
            TB_Fill.ForeColor = TB_Fill.BackColor.GetInverseColor();
            PE_Main.SelectColor = TB_Fill.BackColor;
        }

        private void RB_Clip_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_Clip.Checked)
            {
                PE_Main.CurToolType = PicEditor.ToolType.Clip;
                Bn_ConfirmClip.Visible = true;
            }
            else
            {
                Bn_ConfirmClip.Visible = false;
            }
        }

        private void RB_Pencil_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_Pencil.Checked)
            {
                PE_Main.CurToolType = PicEditor.ToolType.Pencil;
            }
        }

        private void RB_Brush_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_Brush.Checked)
            {
                PE_Main.CurToolType = PicEditor.ToolType.Brush;
            }
        }

        private void RB_Straw_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_Pipette.Checked)
            {
                PE_Main.CurToolType = PicEditor.ToolType.Pipette;
            }
        }

        private void RB_MagicWand_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_MagicWand.Checked)
            {
                CB_InverseSelect.Visible = true;
                NUD_Similarly.Visible = true;
                Bn_ConfirmFill.Visible = true;
                PE_Main.CurToolType = PicEditor.ToolType.MagicWand;
            }
            else
            {
                CB_InverseSelect.Visible = false;
                NUD_Similarly.Visible = false;
                Bn_ConfirmFill.Visible = false;
            }
        }

        private void RB_BasePoint_CheckedChanged(object sender, EventArgs e)
        {
            if (RB_BasePoint.Checked)
            {
                PE_Main.CurToolType = PicEditor.ToolType.Locate;
            }
        }

        private void Bn_FindFillColor_Click(object sender, EventArgs e)
        {
            double similarly = (double)NUD_DeletaColor.Value / 100.0;
            Bn_FindFillColor.BackColor = PE_Main.FindCollisionlessColor(similarly) ? Color.LightGreen : Color.Red;
        }

        private void Bn_ConfirmFill_Click(object sender, EventArgs e)
        {
            PE_Main.ConfirmMagicWand();
        }

        private void NUD_Scalar_ValueChanged(object sender, EventArgs e)
        {
            PE_Main.Scalar = (int)NUD_Scalar.Value;
        }

        private void Bn_Save_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_ImgEntity.Name))
            {
                MessageBox.Show(this, "请填写图片名称后保存", "提醒", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (string.IsNullOrWhiteSpace(_ImgEntity.BaseOffsetStr))
            {
                if (MessageBox.Show(this, "确定不为图片设置基准点吗?", "警告", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.Cancel)
                {
                    return;
                }
            }
            using (MemoryStream ms = new MemoryStream())
            {
                PE_Main.Image.Save(ms, ImageFormat.Bmp);
                _ImgEntity.Bin = ms.ToArray();
            }

            DialogResult = DialogResult.OK;
        }

        private void Bn_ConfirmClip_Click(object sender, EventArgs e)
        {
            PE_Main.ClipIt();
        }

        private void NUD_Similarly_ValueChanged(object sender, EventArgs e)
        {
            PE_Main.Semblance = (double)NUD_Similarly.Value;
        }

        private void CB_InverseSelect_CheckedChanged(object sender, EventArgs e)
        {
            PE_Main.InverseSelect = CB_InverseSelect.Checked;
        }

        private void ImgEditor_Shown(object sender, EventArgs e)
        {
            TB_Fill.Text = "FF00FF";
        }

        private void PE_Main_OnSelectedColorChanged(object sender, SelectedColorChangedEventArgs e)
        {
            TB_Fill.Text = (e.Color.ToArgb() & 0XFFFFFF).ToString("X2");
        }

        private void Bn_Reset_Click(object sender, EventArgs e)
        {
            ResetImage();
        }

        private void PE_Main_OnSelectedPointChanged(object sender, SelectedPointChangedEventArgs e)
        {
            _ImgEntity.BaseOffsetStr = TB_BaseOffset.Text = e.Point.MakeString();
        }

        private void TB_BaseOffset_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!_OffsetRegex.IsMatch(TB_BaseOffset.Text))
            {
                e.Cancel = true;
            }
        }

        private void ImgEditor_Click(object sender, EventArgs e)
        {

        }

        private void TB_BaseOffset_Enter(object sender, EventArgs e)
        {
            if (!RB_BasePoint.Checked)
            {
                RB_BasePoint.Checked = true;
            }
        }

    }
}
